/* 
 *	Copyright (C) 2009-2010 miaohua
 *	http://code.google.com/p/lrcshower/
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */

#include "Stdafx.h"
#include <Windows.h>
#include <cerrno>
#include <string>
#include <sstream>
#include "Config.h"
#include "HelperFunctions.h"
using namespace std;

bool WildStr2MultiBytes(const wstring & Src, string & Dest)
{
     char * Buf = new char [Src.size()*2+2];
     if( WideCharToMultiByte( CP_ACP, 0, Src.c_str(), -1, Buf, Src.size()*2+2, NULL, NULL ) == 0 )
     {
#ifdef _DEBUG
         _Dbg_Printf(_T("WideCharToMultiByte fails, the last error code is %d \n"), GetLastError());
#endif
         delete[] Buf;
         return false;
     }

     Dest = Buf;
     delete[] Buf;
     return true; 
}

bool MultiBytes2WildStr(const string & Src, wstring & Dest)
{
     wchar_t * Buf = new wchar_t[Src.size()+1];
     if( MultiByteToWideChar( CP_ACP, 0, Src.c_str(), Src.size()+1, Buf, Src.size()+1)  == 0 )
     {
#ifdef _DEBUG
         _Dbg_Printf(_T("MultiByteToWideChar fails, the last error code is %d\n"), GetLastError());
#endif
         delete [] Buf;
         return false;
     }

     Dest = Buf;
     delete [] Buf;
     return true; 
}

void _Dbg_Printf (const TCHAR * Format,...)
{
     #define MAX_DBG_MSG_LEN  4096
     TCHAR Buf[MAX_DBG_MSG_LEN];
    
     va_list Ap;
     va_start(Ap, Format);

     _vsntprintf_s(Buf, MAX_DBG_MSG_LEN-1, _TRUNCATE, Format, Ap);
     OutputDebugString(Buf);

     va_end(Ap);
}

tstring StrFormat(const TCHAR * Format,...)
{
     #define MAX_DBG_MSG_LEN  4096
     TCHAR Buf[MAX_DBG_MSG_LEN];
    
     va_list Ap;
     va_start(Ap, Format);
     _vsntprintf_s(Buf, MAX_DBG_MSG_LEN-1, _TRUNCATE, Format, Ap);
     va_end(Ap);

     return Buf;
}

void TrimStr(tstring & Str)
{
     const basic_string <TCHAR>::size_type npos = tstring::npos;
         
     // Trim the heading spaces
     basic_string <TCHAR>::size_type Idx = Str.find_first_not_of(' ');
     if( Idx == npos ) 
     {
         //all of the string charaters are space
         Str.clear();
         return;
     }
         
     Str = Str.substr(Idx);
         
     // Trim the ending '\n' & '\r'
     while( Str.size() > 0 && (Str[Str.size()-1] == '\r' || Str[Str.size()-1] == '\n') )
            Str = Str.substr(0, Str.size()-1);
     // Trim the ending spaces
     Idx = Str.find_last_not_of(' ');
     if( Idx == npos ) return;
     Str = Str.substr(0, Idx+1);
}

void ToLower(tstring & Str)
{
     tstring::size_type Size = Str.size();
     tstring Res;
     for( tstring::size_type i = 0; i < Size; ++i )
     {
          TCHAR ch = _totlower(Str[i]);
          Str[i] = ch;
     }
}


DWORD CvtHexToNum(const tstring & Str)   
{   
      DWORD Num = 0;   
      int Size = Str.size();
      for( int i = 0; i < Size; ++ i )   
      {   
           TCHAR Tmp = Str[i];   
           if(Tmp == ' ') continue;   
           Num >>= 4;   
           if( Tmp >= '0' && Tmp <= '9' )   
               Num |= (Tmp - '0');
           else if( Tmp >= 'a' && Tmp <= 'f' )
               Num |=(Tmp - 'a')+10;   
           else  if(Tmp >= 'A' && Tmp <= 'F')
               Num |=(Tmp - 'A')+10;   
           else 
               break;
      }   
         
      return Num;   
}   

tstring CvtNumToHex(DWORD Num)
{
      static TCHAR Map[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
      DWORD Mask = 0xf;
      tstring Result;
      while(Num)
      {
          Result = Map[Num & Mask] + Result;
          Num >>= 4;
      }

      if( Result.empty() ) return _T("0");
      return Result;
}

tstring IntToStr(int i)
{
      TCHAR Res[MAX_BUF_LEN];
      _itot_s(i, Res, MAX_BUF_LEN, 10);
      return Res;
}


std::string ChEncode(const std::string & SongName)
{
      char * Name = new char[SongName.size()+1]();
      strcpy_s(Name, SongName.size()+1, SongName.c_str());
      const char * Delimit = " ";
      char *Token = NULL;
      char *Next_Token = NULL;
      string Res, Word;
    
      Token = strtok_s(Name, Delimit, &Next_Token);
      while( Token )
      {
             int Size = strlen(Token);
             if( Res.size() > 0 )
                 Res += '+';
             for( int i = 0; i < Size; ++i )
             {
                  unsigned int Tmp = Token[i];
                  // test wether it is a chinese code
                  if( Tmp & 0xffffff00 )
                  {
                      Tmp &= 0x000000ff;
                      stringstream Fmt;
                      Fmt << hex << uppercase <<"%"<<Tmp;
                      Fmt >> uppercase >> Word;
                      Res += Word;
                  } else
                      Res += Token[i];
             }
             Token = strtok_s(NULL, Delimit, &Next_Token);
     }
      
     delete[] Name;

     return Res;
}

unsigned int FormatNum(const tstring & Num)
{
      if( Num.empty() ) return 0;

      // Convert it to num;
      int Size = Num.size();
      unsigned int Result = 0;
      for( int i = 0; i < Size; ++i )
           if( Num[i] != ',' )
               Result = Result * 10 + Num[i]- '0';

      return Result;
}    


bool GetTmpDir(tstring & Path, const tstring & TmpDirName)
{
      TCHAR szPath[MAX_PATH];
      if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )
          return false;

      Path = szPath;
      basic_string <TCHAR>::size_type Idx = Path.find_last_of('\\');
      if( Idx == tstring::npos ) return false;

      Path = Path.substr(0, Idx) + _T("\\") + TmpDirName;
      if( _tmkdir(Path.c_str()) == -1 )
          if( errno != EEXIST )
              return false;

      return true;
}

tstring UrlGenHelper(const tstring & Template, const tstring & Word, int Count)
{
     tstring Encode;
#ifdef UNICODE
     std::string Tmp;
     WildStr2MultiBytes(Word, Tmp);
     MultiBytes2WildStr(ChEncode(Tmp), Encode);
#else
     Encode = ChEncode(Word);
#endif  

     TCHAR LrcUrl[MAX_BUF_LEN];
     _stprintf_s(LrcUrl, MAX_BUF_LEN, Template.c_str(), Encode.c_str(), Count);

     return LrcUrl;

}

bool IsFileExist(const tstring & FullPath)
{
     WIN32_FIND_DATA Wfd;   
     HANDLE Finder = FindFirstFile(FullPath.c_str(),&Wfd);   
     if( Finder == INVALID_HANDLE_VALUE )   
         return false;   
       
     FindClose(Finder);   
     return true;  
}
